#include "unixnetworkmanager.h"
#include "protocolNetwork.h"
#ifdef OS_UNIX

UNIXNetworkManager::UNIXNetworkManager() : _maxfd(-1), _mainBuffer(new char[4096]) { }

void UNIXNetworkManager::generateReadFs() {
  FD_ZERO(&_readfs);
  for (std::list<Player *>::iterator it = _players.begin(); it != _players.end(); ++it)
    FD_SET((*it)->getSocket()->UNIXGetSocket(), &_readfs);
}

void UNIXNetworkManager::generateWriteFs()
{
  _hasWriteFs = false;
  FD_ZERO(&_writefs);
  for (std::list<Player *>::iterator it = _players.begin(); it != _players.end(); ++it)
    {
      if (!((*it)->getWriteBuffer()->isEmpty()))
	{
	  _hasWriteFs = true;
	  FD_SET((*it)->getSocket()->UNIXGetSocket(), &_writefs);
	}
    }
}

void UNIXNetworkManager::addPlayer(Player *p)
{
  if (p && p->getSocket())
    {
      _players.push_back(p);
      if (p->getSocket()->UNIXGetSocket() > _maxfd)
	_maxfd = p->getSocket()->UNIXGetSocket();
      UNIXNetworkManager::generateReadFs();
    }
}

void UNIXNetworkManager::removePlayer(Player *p)
{
  _players.remove(p);
  p->getSocket()->disconnect();
}

void UNIXNetworkManager::run(long uTimeout)
{
  struct timeval timeout;
  timeout.tv_sec = 0;
  timeout.tv_usec = uTimeout * 1000;
  UNIXNetworkManager::generateWriteFs();
  unsigned int size;

  UNIXNetworkManager::generateReadFs();
  ::memcpy(&_readfscpy, &_readfs, sizeof(fd_set));
  if (::select(_maxfd + 1, &_readfs, (_hasWriteFs == true) ? &_writefs : NULL, NULL,
	       (uTimeout == -1) ? NULL : &timeout) == -1)
    {
      return ;
    }
  for (std::list<Player *>::iterator it = _players.begin(); it != _players.end()
         ; ++it)
    {
      if ((*it)->getSocket() && FD_ISSET((*it)->getSocket()->UNIXGetSocket(), &_readfs))
        {
	  if ((*it)->getSocket()->isServerSock())
            {
	      std::cout << "Waiting for client" << std::endl;
	      Player *n = new Player((*it)->getSocket()->waitForClient());
	      UNIXNetworkManager::addPlayer(n);	      
            } 
	  else
	    {
	      size = (*it)->getSocket()->read(_mainBuffer, 512);
	      if (size == 0)
		{
		  std::cout << "client disconnected" << std::endl;
		  (*it)->getSocket()->disconnect();
		  it = _players.erase(it);
		  UNIXNetworkManager::generateReadFs();
		  UNIXNetworkManager::generateWriteFs();
		}
	      else
		{
		  std::cout << "UNIXNetworkManager::run() SIZE = " << size << std::endl;
		  (*it)->getReadBuffer()->append(_mainBuffer, size);
		  (*it)->getProto()->readEvent(*it);
		}
	    }
        }
      else if ((*it)->getSocket() && FD_ISSET((*it)->getSocket()->UNIXGetSocket(), &_writefs))
	{
	  std::cout << "UNIXNetworkManager::writing..." << std::endl;
	    
	  size = (*it)->getWriteBuffer()->extract(_mainBuffer, 512);
	  std::cout << "UNIXNetworkManager::after_extract" << std::endl;
	  // if ((*it)->getSocket()) {
	  //   (*it)->getSocket()->send(_mainBuffer, size);
	  // }
	  std::cout << "UNIXNetworkManager::after_send" << std::endl;
	    
        }
    }
}

void UNIXNetworkManager::runGame(long uTimeout)
{
  struct timeval timeout;
  timeout.tv_sec = 0;
  timeout.tv_usec = uTimeout * 1000;
  UNIXNetworkManager::generateWriteFs();
  unsigned int size;

  UNIXNetworkManager::generateReadFs();
  ::memcpy(&_readfscpy, &_readfs, sizeof(fd_set));

  std::cout << "avant le select de mort" << std::endl;

  if (::select(_maxfd + 1, &_readfs, NULL, NULL,
	       (uTimeout == -1) ? NULL : &timeout) == -1)
    {
      return ;
    }

  std::cout << "deblocage PD" << std::endl;

  for (std::list<Player *>::iterator it = _players.begin(); it != _players.end(); ++it)
    {
      if ((*it)->getSocket() && FD_ISSET((*it)->getSocket()->UNIXGetSocket(), &_readfs))
        {
	  if ((*it)->getSocket()->isServerSock())
            {
	      std::cout << "Quelqu'un me parle !!" << std::endl;
	      size = (*it)->getSocket()->read(_mainBuffer, 512);
	      std::cout << _mainBuffer << std::endl;
            }
	}
    }
}

#endif
